package com.jalarbee.stock.product.business;

import com.jalarbee.core.business.PricedEntity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;

import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Type;

import com.jalarbee.stock.category.business.Category;
import javax.persistence.NamedQuery;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE", discriminatorType = DiscriminatorType.STRING)
@NamedQuery(name="active.products", query="SELECT p FROM Product p WHERE p.status=:status")
public abstract class Product extends PricedEntity implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    
    @Type(type = "com.jalarbee.core.types.QuantityType")
    @Columns(columns= {
        @Column(name="SIZE"),
        @Column(name="UNIT")
    })
    private Quantity smallestTradabeUnit;
    @Column(unique = true, nullable = false)
    private String name;

    private String description;

    
    @ManyToOne(optional = false, cascade = {CascadeType.MERGE, CascadeType.REMOVE})
    @JoinColumn(name = "DEFAULT_CATEGORY_ID", nullable = false)
    private Category defaultCategory;

    @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    @JoinTable(name = "PRODUCT_CATEGORY",
    joinColumns = {
        @JoinColumn(name = "PRODUCT_ID")},
    inverseJoinColumns = {
        @JoinColumn(name = "CATEGORY_ID")})
    private List<Category> categories = new ArrayList<Category>();

    @Enumerated(EnumType.STRING)
    private ProductAvailability availability = ProductAvailability.IN_STORE;

    @Enumerated(EnumType.STRING)
    private ProductStatus status;
    
    public ProductAvailability getAvailability() {
        return availability;
    }

    public void setAvailability(ProductAvailability availability) {
        this.availability = availability;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Category getDefaultCategory() {
        return defaultCategory;
    }

    public void setDefaultCategory(Category defaultCategory) {
        this.defaultCategory = defaultCategory;
    }

    public List<Category> getCategories() {
        return categories;
    }

    public void setCategories(List<Category> categories) {
        this.categories = categories;
    }

    public Quantity getSmallestTradabeUnit() {
        return smallestTradabeUnit;
    }

    public void setSmallestTradabeUnit(Quantity smallestTradabeUnit) {
        this.smallestTradabeUnit = smallestTradabeUnit;
    }

    public ProductStatus getStatus() {
        return status;
    }

    public void setStatus(ProductStatus status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return name;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj == null)
            return false;
        if(!(obj instanceof Product))
            return false;
        Product p = (Product) obj;
        return p.name.equals(this.name) 
                && (p.defaultCategory != null ? p.defaultCategory.equals(this.defaultCategory) : true)
                && (p.description != null ? p.description.equals(this.description) : true);
    }

    @Override
    public int hashCode() {
        return name.hashCode() * 12 + defaultCategory.hashCode() * 3 - 57;

    }

}
